/*******************************************************************************
 * @project: aohuaproject
 * @package: com.aohua.excel
 * @file: AbstractExcelService.java
 * @author: fionn
 * @created: 2015年11月11日
 * @purpose:
 * 
 * @version: 1.1
 * 
 * 
 * Copyright 2015 HAND All rights reserved.
 ******************************************************************************/
package com.aohua.excel;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;


/**
 * @author fionn
 *
 */
public abstract class AbstractExcelService<T> implements IExcelService<T> {

    protected static Logger log = Logger.getLogger(AbstractExcelService.class);
    protected File excelFile;
    protected Workbook workbook;
    private FileInputStream inp;
    
    public AbstractExcelService(){
    }
    /* (non-Javadoc)
     * @see com.ebm.tools.service.IExcelService#open(java.io.File)
     */
    @Override
    public void open(File excelFile) throws FileNotFoundException, IOException {
        this.excelFile = excelFile;
        this.inp = new FileInputStream(excelFile);
        this.workbook = new XSSFWorkbook(inp);
    }

    /* (non-Javadoc)
     * @see com.ebm.tools.service.IExcelService#open4Write(java.io.File)
     */
    @Override
    public void open4Write(File excelFile) throws FileNotFoundException {
        this.excelFile = excelFile;
        this.workbook = new XSSFWorkbook();
    }

    /* (non-Javadoc)
     * @see com.ebm.tools.service.IExcelService#save()
     */
    @Override
    public void save() {
        FileOutputStream otp = null;
        try {
            otp = new FileOutputStream(excelFile);
            workbook.write(otp);
        } catch (FileNotFoundException e) {
            log.error(e.getMessage(), e);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }finally {
            if(otp != null) {
                try {
                    otp.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }

    /* (non-Javadoc)
     * @see com.ebm.tools.service.IExcelService#close()
     */
    @Override
    public void close() {
        if(inp != null) {
            try {
                inp.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if(workbook != null) {
            try {
//                workbook.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /* (non-Javadoc)
     * @see com.ebm.tools.service.IExcelService#getSheets()
     */
    @Override
    public Sheet[] getSheets() {
        int count = workbook.getNumberOfSheets();
        Sheet[] sheets = new Sheet[count];
        for(int i=0; i< count; i++) {
            sheets[i] = workbook.getSheetAt(i);
        }
        return sheets;
    }

    public Sheet getSheet(String sheetname) {
        return workbook != null ? workbook.getSheet(sheetname) : null;
    }
    
    /* (non-Javadoc)
     * @see com.ebm.tools.service.IExcelService#createSheet(java.lang.String)
     */
    @Override
    public Sheet createSheet(String sheetName) {
        return workbook.createSheet(sheetName);
    }

    /* (non-Javadoc)
     * @see com.ebm.tools.service.IExcelService#read(org.apache.poi.ss.usermodel.Sheet)
     */
    @Override
    public List<T> read(Sheet sheet) {
        Iterator<Row> rowit = sheet.rowIterator();
        for(int i=0; i< getRowBeginIndex(); i++) {
            rowit.next();
        }
        List<T> vos = new ArrayList<T>();
        Row row = null;
        while(rowit.hasNext()) {
            row = rowit.next();
            T t = getExcelVO(row);
            if(t != null)      vos.add(t);
        }
        return vos;
    }

    /* (non-Javadoc)
     * @see com.ebm.tools.service.IExcelService#write(org.apache.poi.ss.usermodel.Sheet, java.lang.Object)
     */
    @Override
    public void write(Sheet sheet, T data) {
        int lastRowIndx = sheet.getLastRowNum();
        Row row = sheet.createRow(lastRowIndx+1);
        writeRow(row, data);
    }

    /* (non-Javadoc)
     * @see com.ebm.tools.service.IExcelService#write(org.apache.poi.ss.usermodel.Sheet, java.util.List)
     */
    @Override
    public void write(Sheet sheet, List<T> datas) {
        int lastRowIndx = sheet.getLastRowNum();
        Row row  = null;
        for(T vo : datas) {
            row = sheet.createRow(lastRowIndx + 1);
            writeRow(row, vo);
            lastRowIndx ++;
        }
    }
    
    public abstract int getRowBeginIndex();

    protected abstract T getExcelVO(Row row);
    
    protected abstract void writeRow(Row row, T data);
    
    protected String getStringCellValue(Cell cell) {
        if(cell == null) return "";
        String value = cell.getStringCellValue();
        return (value != null && !"".equals(value.trim())) ? value.trim() : "";
    }

    protected List<T> read(String excelpath, String sheetName){
        List<T> ts = new ArrayList<T>();
        try {
            open(new File(excelpath));
            Sheet sheet = getSheet(sheetName);
            ts = read(sheet);
        } catch (Exception e) {
            e.printStackTrace(System.out);
            log.error(e.getMessage(), e);
        } finally {
            close();
        }
        return ts;
    }
    
}
